use std::sync::Arc;

use pdata::{internal::data::protogen::collector::metrics::v1::ExportMetricsServiceRequest, protogen::collector::logs::v1::ExportLogsServiceRequest};
use pdata::internal::data::protogen::collector::trace::v1::ExportTraceServiceRequest;
use tracing::info;

use crate::consumer::{ConsumeLogs, ConsumeMetrics, ConsumeTraces};

/// Simple debug exporter which prints incoming data to stdout in a concise format
pub struct DebugExporter {
    /// When true, print full pretty structures; otherwise print concise summary
    pub verbose: bool,
}

impl DebugExporter {
    pub fn new(verbose: bool) -> Arc<Self> {
        Arc::new(Self { verbose })
    }
}

#[tonic::async_trait]
impl ConsumeTraces for DebugExporter {
    async fn consume(&self, data: ExportTraceServiceRequest) {
        if self.verbose {
            info!(target: "exporter::debug", "traces(full) = {:#?}", data);
        } else {
            let mut resource_spans_count = 0usize;
            let mut scope_spans_count = 0usize;
            let mut spans_count = 0usize;
            for rs in &data.resource_spans {
                resource_spans_count += 1;
                for ss in &rs.scope_spans {
                    scope_spans_count += 1;
                    spans_count += ss.spans.len();
                }
            }
            info!(target: "exporter::debug", "traces(summary): resources={}, scopes={}, spans={}", resource_spans_count, scope_spans_count, spans_count);
        }
    }
}

#[tonic::async_trait]
impl ConsumeMetrics for DebugExporter {
    async fn consume(&self, data: ExportMetricsServiceRequest) {
        if self.verbose {
            info!(target: "exporter::debug", "metrics(full) = {:#?}", data);
        } else {
            let mut resource_metrics_count = 0usize;
            let mut scope_metrics_count = 0usize;
            let mut metric_count = 0usize;
            for rm in &data.resource_metrics {
                resource_metrics_count += 1;
                for sm in &rm.scope_metrics {
                    scope_metrics_count += 1;
                    metric_count += sm.metrics.len();
                }
            }
            info!(target: "exporter::debug", "metrics(summary): resources={}, scopes={}, metrics={}", resource_metrics_count, scope_metrics_count, metric_count);
        }
    }
}

#[tonic::async_trait]
impl ConsumeLogs for DebugExporter {
    async fn consume(&self, data: ExportLogsServiceRequest) {
        info!(target: "exporter::debug", "logs = {:#?}", data);
    }
}
